package com.grad.webstudy.annota.resolver;

import com.grad.webstudy.annota.ApiAuthorization;
import com.grad.webstudy.constants.RoleConstants;
import com.grad.webstudy.constants.TokenConstants;
import com.grad.webstudy.context.UserContext;
import com.grad.webstudy.enums.ExceptionEnums;
import com.grad.webstudy.exceptions.CustomException;
import com.grad.webstudy.model.Token;
import com.grad.webstudy.service.RoleUserService;
import com.grad.webstudy.service.TokenService;
import com.grad.webstudy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Author: zjf
 * @Date: 2020/1/19 23:09
 * @Description:
 */
@Component
public class ApiAuthorizationInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UserService userService;

    @Autowired
    private RoleUserService roleUserService;


    /**
     * 在请求执行前，验证权限相关，验证通过的，
     * 将用户信息放入ThreadLocal中
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws MissingServletRequestParameterException
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws MissingServletRequestParameterException {

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        ApiAuthorization apiAuthorization = method.getAnnotation(ApiAuthorization.class);
        //如果没有注解，直接放行
        if (apiAuthorization == null) {
            return true;
        }
        String token = request.getHeader(TokenConstants.TOKEN);

        //token校验失败，抛出自定义异常
        if (!tokenService.checkToken(token)) {
            throw new CustomException(ExceptionEnums.TOKEN_INVALID.getCode(),
                    ExceptionEnums.TOKEN_INVALID.getMessage());

        }


        
        tokenService.refresh(token);

        Token tokenEntity = tokenService.getToken(token);

        String userId = tokenEntity.getUserId();

        // 1.查用户角色
        List<Integer> roleIds = roleUserService.queryRoleIdsByUserId(Integer.parseInt(userId));

        //如果用户角色包含超级管理员的角色id，直接返回,不用验证权限
        if (roleIds.contains(RoleConstants.ADMIN)) {
            UserContext.setLoginUser(tokenEntity.getUser());
            return true;
        }

        //2. 非超级管理员用户获取权限并验证
        List<String> resultAuth = userService.queryUserAuth(Integer.parseInt(userId));

        //3. 获取需要验证的权限
        String auth = apiAuthorization.auth();

        if (Objects.isNull(auth) || auth.length() == 0) {
            throw new CustomException(ExceptionEnums.CUSTOM_ERROR.getCode(),
                    "注解参数不能为空");
        }

        //由于获取的权限格式为 xxx:xxx:xxx之类的，
        // 以：分隔后，会有多级权限，根据顺序分为一级、二级，依次类推
        String[] authLevel = auth.split(":");

        int authLength = authLevel.length;

        int start = 0;
        String[] authLevels = new String[authLength];

        //权限数组构造
        while (authLength > 0) {

            if (start == 0) {
                //一级权限直接赋值
                authLevels[start] = authLevel[start];
            } else {
                //多级权限拼接，根据构造的权限数组拼接
                //由于传入的权限已经分隔，需要借助新构造的权限数组来拼接权限
                //新构造数组的下标就代表了是第几级权限
                authLevels[start] = authLevels[start - 1] + ":" + authLevel[start];
            }
            start++;
            authLength--;
        }

        for (int i = 0; i < authLevels.length; i++) {
            //验证权限
            if (resultAuth.contains(authLevels[i])) {
                UserContext.setLoginUser(tokenEntity.getUser());
                return true;
            }
        }
        //权限验证完毕后依然没有返回则抛出 权限异常
        throw new CustomException(ExceptionEnums.AUTH_FORBIDDEN.getCode(),
                ExceptionEnums.AUTH_FORBIDDEN.getMessage());

    }


    /**
     * 请求执行完成之后，
     * 从ThreadLocal中删除用户信息
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        if (!(handler instanceof HandlerMethod)) {
            return ;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        ApiAuthorization apiAuthorization = method.getAnnotation(ApiAuthorization.class);
        //如果没有注解，直接放行
        if (apiAuthorization == null) {
            return ;
        }
        UserContext.removeLoginUser();
    }


}
